home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -seriously_amiga- / shareware / programming / c / amivogl-mdev / src / polygons.c < prev    next >
C/C++ Source or Header  |  1998-01-12  |  24KB  |  1,278 lines

  1. #include <stdio.h>
  2. #include "vogl.h"
  3.  
  4. /* --------------------------------------------------------------------- */
  5.  
  6. #ifdef AZTEC_C
  7. #include <math.h>
  8. #else
  9. extern    double    cos();
  10. extern    double    sin();
  11. #endif
  12.  
  13. /* ---------------------------------------------------------------------
  14.  * Definitions:
  15.  */
  16.  
  17. #define MAX(x, y)    ((x) > (y) ? (x) : (y))
  18. #define MIN(x, y)    ((x) < (y) ? (x) : (y))
  19. #define ABS(x)        ((x) < 0 ? -(x) : (x))
  20.  
  21. /* ---------------------------------------------------------------------
  22.  * Local Variables:
  23.  */
  24. static float    F[6][4], S[6][4], I[4], p[MAXVERTS][4];
  25. static int    nout, first[6], numv;
  26. static long    polymodeflag = PYM_FILL;
  27. static int    ip1[MAXVERTS], ip2[MAXVERTS];
  28.  
  29. /*
  30.  *  Orientation of backfacing polygons(in screen coords)
  31.  */
  32. static    int    clockwise = 1;
  33.  
  34. /* ---------------------------------------------------------------------
  35.  * Prototypes:
  36.  */
  37. #ifdef __PROTOTYPE__
  38.  
  39. static void dopoly(int);                               /* polygons.c      */
  40. static void polyoutline( int, int[], int[]);           /* polygons.c      */
  41. static int checkbacki(void);                           /* polygons.c      */
  42. static void polyclip(register int);                    /* polygons.c      */
  43. static void shclip( float[4], int);                    /* polygons.c      */
  44. static void shclose(int);                              /* polygons.c      */
  45. static intersect( int, register Vector,                /* polygons.c      */
  46.    register Vector);
  47. static visible(int);                                   /* polygons.c      */
  48.  
  49. #else    /* __PROTOTYPE__ */
  50.  
  51. static void dopoly();                                  /* polygons.c      */
  52. static void polyoutline();                             /* polygons.c      */
  53. static int checkbacki();                               /* polygons.c      */
  54. static void polyclip();                                /* polygons.c      */
  55. static void shclip();                                  /* polygons.c      */
  56. static void shclose();                                 /* polygons.c      */
  57. static intersect();                                    /* polygons.c      */
  58. static visible();                                      /* polygons.c      */
  59.  
  60. #endif    /* __PROTOTYPE__ */
  61.  
  62. /*
  63.  * concave
  64.  *
  65.  *    signal wether or not polygons are concave (not a lot of use at the moment).
  66.  */
  67. void concave(Boolean yesno)
  68. {
  69. vdevice.concave = yesno;
  70. }
  71.  
  72. /* ------------------------------------------------------------------------ */
  73.  
  74. /*
  75.  * backface
  76.  *
  77.  *    Turns on culling of backfacing polygons. A polygon is
  78.  * backfacing if it's orientation in *screen* coords is clockwise.
  79.  */
  80. void backface(int onoff)
  81. {
  82. vdevice.attr->a.backface = onoff;
  83. clockwise = 1;
  84. }
  85.  
  86. /* ------------------------------------------------------------------------ */
  87.  
  88. /*
  89.  * frontface
  90.  *
  91.  *    Turns on culling of frontfacing polygons. A polygon is
  92.  * frontfacing if it's orientation in *screen* coords is anti-clockwise.
  93.  */
  94. void frontface(int onoff)
  95. {
  96. vdevice.attr->a.backface = onoff;
  97. clockwise = 0;
  98. }
  99.  
  100. /* ------------------------------------------------------------------------ */
  101.  
  102. /*
  103.  * polymode
  104.  *
  105.  *    Sets the polygon filling mode - only filled or outlined supported
  106.  */
  107. void polymode(long mode)
  108. {
  109. /*
  110.  * On older SGI Machines this call used to work... On the newer
  111.  * boxes it doesn't do anything. If you want the old stuff then
  112.  * #define OLD_SGI_BOXES somewhere.
  113.  */
  114. #ifdef OLD_SGI_BOXES
  115. polymodeflag = mode;
  116. #endif
  117. }
  118.  
  119. /* ------------------------------------------------------------------------ */
  120.  
  121. /*
  122.  * dopoly
  123.  *
  124.  *    do a transformed polygon with n edges using fill
  125.  */
  126. static void dopoly(int n)
  127. {
  128. int    i;
  129. char    buf[100];
  130.  
  131. if (n > MAXVERTS) {
  132.     sprintf(buf, "dopoly: can't fill a polygon with more than %d vertices", MAXVERTS);
  133.     verror(buf);
  134.     }
  135.  
  136. if (!vdevice.clipoff) {
  137.     polyclip(n);
  138.     }
  139. else {
  140.     nout = n;
  141.     for (i = 0; i < n; i++) {
  142.         ip1[i] = WtoVx(p[i]);
  143.         ip2[i] = WtoVy(p[i]);
  144.         }
  145.     }
  146.  
  147.  
  148. if (vdevice.attr->a.backface && checkbacki()) {
  149.     vdevice.fill = 0;
  150.     return;
  151.     }
  152.  
  153. if (vdevice.fill) {
  154.     if (nout > 2) {
  155.         (*vdevice.dev.Vfill)(nout, ip1, ip2);
  156.         }
  157.     }
  158. else {
  159.     vdevice.cpVx = ip1[0];
  160.     vdevice.cpVy = ip2[0];
  161.     vdevice.cpVvalid = 0;
  162.     polyoutline(nout, ip1, ip2);
  163.     }
  164.  
  165. vdevice.fill = 0;
  166. }
  167.  
  168. /* ------------------------------------------------------------------------ */
  169.  
  170. /*
  171.  * polyoutline
  172.  *
  173.  *    draws a polygon outline from already transformed points.
  174.  */
  175. static void polyoutline(
  176.   int n,
  177.   int ipx[],
  178.   int ipy[])
  179. {
  180. int    i;
  181.  
  182. if (n > 2) {
  183.     for (i = 1; i < n; i++) {
  184.         (*vdevice.dev.Vdraw)(ipx[i], ipy[i]);
  185.  
  186.         vdevice.cpVx = ipx[i];
  187.         vdevice.cpVy = ipy[i];
  188.         }
  189.     (*vdevice.dev.Vdraw)(ipx[0], ipy[0]);
  190.  
  191.     vdevice.cpVx = ipx[0];
  192.     vdevice.cpVy = ipy[0];
  193.     }
  194. }
  195.  
  196. /* ------------------------------------------------------------------------ */
  197.  
  198. /*
  199.  * polyobj
  200.  *
  201.  *    construct a polygon from a object token list.
  202.  */
  203. void polyobj(
  204.   int n,
  205.   Token dp[],
  206.   int fill)
  207. {
  208. int    i, j;
  209. float    vect[4], result[4];
  210.  
  211. for (i = 0, j = 0; i < n; i++, j += 3) {
  212.     vect[V_X] = dp[j + V_X].f;
  213.     vect[V_Y] = dp[j + V_Y].f;
  214.     vect[V_Z] = dp[j + V_Z].f;
  215.     vect[V_W] = 1;
  216.     multvector(result, vect, vdevice.transmat->m);
  217.     p[i][V_X] = result[V_X];
  218.     p[i][V_Y] = result[V_Y];
  219.     p[i][V_Z] = result[V_Z];
  220.     p[i][V_W] = result[V_W];
  221.     }
  222.  
  223. if (fill)
  224. vdevice.fill = polymodeflag;
  225. else
  226. vdevice.fill = 0;
  227.  
  228. dopoly(n);
  229.  
  230. vdevice.cpW[V_X] = dp[V_X].f;
  231. vdevice.cpW[V_Y] = dp[V_Y].f;
  232. vdevice.cpW[V_Z] = dp[V_Z].f;
  233. }
  234.  
  235. /* ------------------------------------------------------------------------ */
  236.  
  237. /*
  238.  * poly2
  239.  *
  240.  *    construct a polygon from an (x, y) array of points provided by the user.
  241.  */
  242. void poly2(
  243.   long nv,
  244.   float dp[][2])
  245. {
  246. int    i;
  247. float    np[MAXVERTS][3];
  248.  
  249. if (!vdevice.initialised)
  250. verror("poly2: vogl not initialised");
  251.  
  252. vdevice.fill = 0;
  253.  
  254. for (i = 0; i < (int)nv; i++) {
  255.     np[i][V_X] = dp[i][V_X];
  256.     np[i][V_Y] = dp[i][V_Y];
  257.     np[i][V_Z] = 0.0;
  258.     }
  259.  
  260. poly(nv, np);
  261. }
  262.  
  263. /* ------------------------------------------------------------------------ */
  264.  
  265. /*
  266.  * poly2i
  267.  *
  268.  *    construct a polygon from an (x, y) array of points provided by the user.
  269.  * Icoord version.
  270.  */
  271. void poly2i(
  272.   long nv,
  273.   Icoord dp[][2])
  274. {
  275. int    i;
  276. float    np[MAXVERTS][3];
  277.  
  278. if (!vdevice.initialised)
  279. verror("poly2i: vogl not initialised");
  280.  
  281. vdevice.fill = 0;
  282.  
  283. for (i = 0; i < (int)nv; i++) {
  284.     np[i][V_X] = dp[i][V_X];
  285.     np[i][V_Y] = dp[i][V_Y];
  286.     np[i][V_Z] = 0.0;
  287.     }
  288.  
  289. poly(nv, np);
  290. }
  291.  
  292. /* ------------------------------------------------------------------------ */
  293.  
  294. /*
  295.  * poly2s
  296.  *
  297.  *    construct a polygon from an (x, y) array of points provided by the user.
  298.  * Scoord version.
  299.  */
  300. void poly2s(
  301.   long nv,
  302.   Scoord dp[][2])
  303. {
  304. int    i;
  305. float    np[MAXVERTS][3];
  306.  
  307. if (!vdevice.initialised)
  308. verror("poly2s: vogl not initialised");
  309.  
  310. vdevice.fill = 0;
  311.  
  312. for (i = 0; i < (int)nv; i++) {
  313.     np[i][V_X] = dp[i][V_X];
  314.     np[i][V_Y] = dp[i][V_Y];
  315.     np[i][V_Z] = 0.0;
  316.     }
  317.  
  318. poly(nv, np);
  319. }
  320.  
  321. /* ------------------------------------------------------------------------ */
  322.  
  323. /*
  324.  * polyi
  325.  *
  326.  *    construct a polygon from an (x, y, z) array of points provided by the user.
  327.  * Icoord version.
  328.  */
  329. void polyi(
  330.   long nv,
  331.   Icoord dp[][3])
  332. {
  333. int    i;
  334. float    np[MAXVERTS][3];
  335.  
  336. if (!vdevice.initialised)
  337. verror("polyi: vogl not initialised");
  338.  
  339. vdevice.fill = 0;
  340.  
  341. for (i = 0; i < (int)nv; i++) {
  342.     np[i][V_X] = dp[i][V_X];
  343.     np[i][V_Y] = dp[i][V_Y];
  344.     np[i][V_Z] = dp[i][V_Z];
  345.     }
  346.  
  347. poly(nv, np);
  348. }
  349.  
  350. /* ------------------------------------------------------------------------ */
  351.  
  352. /*
  353.  * polys
  354.  *
  355.  *    construct a polygon from an (x, y, z) array of points provided by the user.
  356.  * Scoord version.
  357.  */
  358. void polys(
  359.   long nv,
  360.   Scoord dp[][3])
  361. {
  362. int    i;
  363. float    np[MAXVERTS][3];
  364.  
  365. if (!vdevice.initialised)
  366. verror("poly2s: vogl not initialised");
  367.  
  368. vdevice.fill = 0;
  369.  
  370. for (i = 0; i < (int)nv; i++) {
  371.     np[i][V_X] = dp[i][V_X];
  372.     np[i][V_Y] = dp[i][V_Y];
  373.     np[i][V_Z] = dp[i][V_Z];
  374.     }
  375.  
  376. poly(nv, np);
  377. }
  378.  
  379. /* ------------------------------------------------------------------------ */
  380.  
  381. /*
  382.  * polf2
  383.  *
  384.  *    construct a filled polygon from an (x, y) array of points provided
  385.  * by the user.
  386.  */
  387. void polf2(
  388.   long nv,
  389.   float dp[][2])
  390. {
  391. int    i;
  392. float    np[MAXVERTS][3];
  393.  
  394. if (!vdevice.initialised)
  395. verror("polf2: vogl not initialised");
  396.  
  397. vdevice.fill = polymodeflag;
  398.  
  399. for (i = 0; i < (int)nv; i++) {
  400.     np[i][V_X] = dp[i][V_X];
  401.     np[i][V_Y] = dp[i][V_Y];
  402.     np[i][V_Z] = 0.0;
  403.     }
  404.  
  405. poly(nv, np);
  406.  
  407. vdevice.fill = 0;
  408. }
  409.  
  410. /* ------------------------------------------------------------------------ */
  411.  
  412. /*
  413.  * polf2i
  414.  *
  415.  *    construct a filled polygon from an (x, y) array of points provided
  416.  * by the user. Icoord version.
  417.  */
  418. void polf2i(
  419.   long nv,
  420.   Icoord dp[][2])
  421. {
  422. int    i;
  423. float    np[MAXVERTS][3];
  424.  
  425. if (!vdevice.initialised)
  426. verror("polf2i: vogl not initialised");
  427.  
  428. vdevice.fill = polymodeflag;
  429.  
  430. for (i = 0; i < (int)nv; i++) {
  431.     np[i][V_X] = dp[i][V_X];
  432.     np[i][V_Y] = dp[i][V_Y];
  433.     np[i][V_Z] = 0.0;
  434.     }
  435.  
  436. poly(nv, np);
  437.  
  438. vdevice.fill = 0;
  439. }
  440.  
  441. /* ------------------------------------------------------------------------ */
  442.  
  443. /*
  444.  * polf2s
  445.  *
  446.  *    construct a filled polygon from an (x, y) array of points provided
  447.  * by the user. Scoord version.
  448.  */
  449. void polf2s(
  450.   long nv,
  451.   Scoord dp[][2])
  452. {
  453. int    i;
  454. float    np[MAXVERTS][3];
  455.  
  456. if (!vdevice.initialised)
  457. verror("polf2s: vogl not initialised");
  458.  
  459. vdevice.fill = polymodeflag;
  460.  
  461. for (i = 0; i < (int)nv; i++) {
  462.     np[i][V_X] = dp[i][V_X];
  463.     np[i][V_Y] = dp[i][V_Y];
  464.     np[i][V_Z] = 0.0;
  465.     }
  466.  
  467. poly(nv, np);
  468.  
  469. vdevice.fill = 0;
  470. }
  471.  
  472. /* ------------------------------------------------------------------------ */
  473.  
  474. /*
  475.  * polfi
  476.  *
  477.  *    construct a filled polygon from an (x, y, z) array of points provided
  478.  * by the user. Icoord version.
  479.  */
  480. void polfi(
  481.   long nv,
  482.   Icoord dp[][3])
  483. {
  484. int    i;
  485. float    np[MAXVERTS][3];
  486.  
  487. if (!vdevice.initialised)
  488. verror("polfi: vogl not initialised");
  489.  
  490. vdevice.fill = polymodeflag;
  491.  
  492. for (i = 0; i < (int)nv; i++) {
  493.     np[i][V_X] = dp[i][V_X];
  494.     np[i][V_Y] = dp[i][V_Y];
  495.     np[i][V_Z] = dp[i][V_Z];
  496.     }
  497.  
  498. poly(nv, np);
  499.  
  500. vdevice.fill = 0;
  501. }
  502.  
  503. /* ------------------------------------------------------------------------ */
  504.  
  505. /*
  506.  * polfs
  507.  *
  508.  *    construct a filled polygon from an (x, y, z) array of points provided
  509.  * by the user. Scoord version.
  510.  */
  511. void polfs(
  512.   long nv,
  513.   Scoord dp[][3])
  514. {
  515. int    i;
  516. float    np[MAXVERTS][3];
  517.  
  518. if (!vdevice.initialised)
  519. verror("polfs: vogl not initialised");
  520.  
  521. vdevice.fill = polymodeflag;
  522.  
  523. for (i = 0; i < (int)nv; i++) {
  524.     np[i][V_X] = dp[i][V_X];
  525.     np[i][V_Y] = dp[i][V_Y];
  526.     np[i][V_Z] = dp[i][V_Z];
  527.     }
  528.  
  529. poly(nv, np);
  530.  
  531. vdevice.fill = 0;
  532. }
  533.  
  534. /* ------------------------------------------------------------------------ */
  535.  
  536. /*
  537.  * poly
  538.  *
  539.  *    construct a polygon from an array of points provided by the user.
  540.  */
  541. void poly(
  542.   long nv,
  543.   float dp[][3])
  544. {
  545. int    i, j;
  546. Vector    vect, result;
  547. Token    *tok;
  548. int    n = nv;
  549.  
  550. if (!vdevice.initialised)
  551. verror("poly: vogl not initialised");
  552.  
  553. if (vdevice.inobject) {
  554.     tok = newtokens(2 + 3 * n);
  555.     tok[0].i = POLY;
  556.     tok[1].i = n;
  557.     for (i = 0, j = 2; i < n; i++, j += 3) {
  558.         tok[j + V_X].f = dp[i][V_X];
  559.         tok[j + V_Y].f = dp[i][V_Y];
  560.         tok[j + V_Z].f = dp[i][V_Z];
  561.         }
  562.     return;
  563.     }
  564.  
  565. for (i = 0; i < n; i++) {
  566.     vect[V_X] = dp[i][V_X];
  567.     vect[V_Y] = dp[i][V_Y];
  568.     vect[V_Z] = dp[i][V_Z];
  569.     vect[V_W] = 1;
  570.     multvector(result, vect, vdevice.transmat->m);
  571.     p[i][V_X] = result[V_X];
  572.     p[i][V_Y] = result[V_Y];
  573.     p[i][V_Z] = result[V_Z];
  574.     p[i][V_W] = result[V_W];
  575.     }
  576.  
  577. dopoly(n);
  578.  
  579. vdevice.cpW[V_X] = dp[0][V_X];
  580. vdevice.cpW[V_Y] = dp[0][V_Y];
  581. vdevice.cpW[V_Z] = dp[0][V_Z];
  582. }
  583.  
  584. /* ------------------------------------------------------------------------ */
  585.  
  586. /*
  587.  * polf
  588.  *
  589.  *    construct a filled polygon from an array of points provided
  590.  * by the user.
  591.  */
  592. void polf(
  593.   long nv,
  594.   float dp[][3])
  595. {
  596. int    i, j;
  597. Vector    vect, result;
  598. Token    *tok;
  599. long    n = nv;
  600.  
  601. if (!vdevice.initialised)
  602. verror("poly: vogl not initialised");
  603.  
  604. vdevice.fill = polymodeflag;
  605.  
  606. if (vdevice.inobject) {
  607.     tok = newtokens(2 + 3 * n);
  608.     tok[0].i = POLYF;
  609.     tok[1].i = n;
  610.     for (i = 0, j = 2; i < n; i++, j += 3) {
  611.         tok[j + V_X].f = dp[i][V_X];
  612.         tok[j + V_Y].f = dp[i][V_Y];
  613.         tok[j + V_Z].f = dp[i][V_Z];
  614.         }
  615.     return;
  616.     }
  617.  
  618. for (i = 0; i < n; i++) {
  619.     vect[V_X] = dp[i][V_X];
  620.     vect[V_Y] = dp[i][V_Y];
  621.     vect[V_Z] = dp[i][V_Z];
  622.     vect[V_W] = 1;
  623.     multvector(result, vect, vdevice.transmat->m);
  624.     p[i][V_X] = result[V_X];
  625.     p[i][V_Y] = result[V_Y];
  626.     p[i][V_Z] = result[V_Z];
  627.     p[i][V_W] = result[V_W];
  628.     }
  629.  
  630. dopoly(n);
  631.  
  632. vdevice.cpW[V_X] = dp[0][V_X];
  633. vdevice.cpW[V_Y] = dp[0][V_Y];
  634. vdevice.cpW[V_Z] = dp[0][V_Z];
  635.  
  636. vdevice.fill = 0;
  637. }
  638.  
  639. /* ------------------------------------------------------------------------ */
  640.  
  641. /*
  642.  * pmv
  643.  *
  644.  *    set the start position of a polygon
  645.  */
  646. void pmv(
  647.   float x,
  648.   float y,
  649.   float z)
  650. {
  651. vdevice.inpolygon = 1;
  652. vdevice.fill = polymodeflag;
  653. numv = 0;
  654. p[numv][V_X] = x;
  655. p[numv][V_Y] = y;
  656. p[numv][V_Z] = z;
  657. p[numv][V_W] = 1.0;
  658. }
  659.  
  660. /* ------------------------------------------------------------------------ */
  661.  
  662. /*
  663.  * pmvi
  664.  *
  665.  *    The integer argument version of pmv.
  666.  */
  667. void pmvi(
  668.   Icoord x,
  669.   Icoord y,
  670.   Icoord z)
  671. {
  672. pmv((float)x, (float)y, (float)z);
  673. }
  674.  
  675. /* ------------------------------------------------------------------------ */
  676.  
  677. /*
  678.  * pmv2i
  679.  *
  680.  *    The integer argument version of pmv2.
  681.  */
  682. void pmv2i(
  683.   Icoord x,
  684.   Icoord y)
  685. {
  686. pmv((float)x, (float)y, vdevice.cpW[V_Z]);
  687. }
  688.  
  689. /* ------------------------------------------------------------------------ */
  690.  
  691. /*
  692.  * pmvs
  693.  *
  694.  *    The integer argument version of pmv.
  695.  */
  696. void pmvs(
  697.   Scoord x,
  698.   Scoord y,
  699.   Scoord z)
  700. {
  701. pmv((float)x, (float)y, (float)z);
  702. }
  703.  
  704. /* ------------------------------------------------------------------------ */
  705.  
  706. /*
  707.  * pmv2s
  708.  *
  709.  *    The integer argument version of pmv2.
  710.  */
  711. void pmv2s(
  712.   Scoord x,
  713.   Scoord y)
  714. {
  715. pmv((float)x, (float)y, vdevice.cpW[V_Z]);
  716. }
  717.  
  718. /* ------------------------------------------------------------------------ */
  719.  
  720. /*
  721.  * pmv2
  722.  *
  723.  *    set up a polygon which will be constructed by a series of
  724.  * move draws in x, y.
  725.  */
  726. void pmv2(
  727.   float x,
  728.   float y)
  729. {
  730. pmv(x, y, vdevice.cpW[V_Z]);
  731. }
  732.  
  733. /* ------------------------------------------------------------------------ */
  734.  
  735.  
  736. /*
  737.  * pdr
  738.  *
  739.  *    add another vertex to the polygon array
  740.  */
  741. void pdr(
  742.   Coord x,
  743.   Coord y,
  744.   Coord z)
  745. {
  746. char    buf[100];
  747.  
  748. numv++;
  749.  
  750. if (numv >= MAXVERTS) {
  751.     sprintf(buf, "pdr: can't draw a polygon with more than %d vertices", MAXVERTS);
  752.     verror(buf);
  753.     }
  754.  
  755. p[numv][V_X] = x;
  756. p[numv][V_Y] = y;
  757. p[numv][V_Z] = z;
  758. p[numv][V_W] = 1.0;
  759. }
  760.  
  761. /* ------------------------------------------------------------------------ */
  762.  
  763. /*
  764.  * rpdr
  765.  *
  766.  *    relative polygon draw.
  767.  */
  768. void rpdr(
  769.   Coord dx,
  770.   Coord dy,
  771.   Coord dz)
  772. {
  773. rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  774. }
  775.  
  776. /* ------------------------------------------------------------------------ */
  777.  
  778. /*
  779.  * rpdr2
  780.  *
  781.  *    relative polygon draw - only (x, y).
  782.  */
  783. void rpdr2(
  784.   Coord dx,
  785.   Coord dy)
  786. {
  787. rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  788. }
  789.  
  790. /* ------------------------------------------------------------------------ */
  791.  
  792. /*
  793.  * rpdri
  794.  *
  795.  *    relative polygon draw. Icoord version.
  796.  */
  797. void rpdri(
  798.   Icoord dx,
  799.   Icoord dy,
  800.   Icoord dz)
  801. {
  802. rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  803. }
  804.  
  805. /* ------------------------------------------------------------------------ */
  806.  
  807. /*
  808.  * rpdr2i
  809.  *
  810.  *    relative polygon draw - only (x, y). Icoord version.
  811.  */
  812. void rpdr2i(
  813.   Icoord dx,
  814.   Icoord dy)
  815. {
  816. rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  817. }
  818.  
  819. /* ------------------------------------------------------------------------ */
  820.  
  821. /*
  822.  * rpdrs
  823.  *
  824.  *    relative polygon draw. Icoord version.
  825.  */
  826. void rpdrs(
  827.   Scoord dx,
  828.   Scoord dy,
  829.   Scoord dz)
  830. {
  831. rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  832. }
  833.  
  834. /* ------------------------------------------------------------------------ */
  835.  
  836. /*
  837.  * rpdr2s
  838.  *
  839.  *    relative polygon draw - only (x, y). Scoord version.
  840.  */
  841. void rpdr2s(
  842.   Scoord dx,
  843.   Scoord dy)
  844. {
  845. rpdr((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  846. }
  847.  
  848. /* ------------------------------------------------------------------------ */
  849.  
  850. /*
  851.  * rpmv
  852.  *
  853.  *    relative polygon move.
  854.  */
  855. void rpmv(
  856.   Coord dx,
  857.   Coord dy,
  858.   Coord dz)
  859. {
  860. pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  861. }
  862.  
  863. /* ------------------------------------------------------------------------ */
  864.  
  865. /*
  866.  * rpmv2
  867.  *
  868.  *    relative polygon move - only (x, y).
  869.  */
  870. void rpmv2(
  871.   Coord dx,
  872.   Coord dy)
  873. {
  874. pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  875. }
  876.  
  877. /* ------------------------------------------------------------------------ */
  878.  
  879. /*
  880.  * rpmvi
  881.  *
  882.  *    relative polygon move. Icoord version.
  883.  */
  884. void rpmvi(
  885.   Icoord dx,
  886.   Icoord dy,
  887.   Icoord dz)
  888. {
  889. pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  890. }
  891.  
  892. /* ------------------------------------------------------------------------ */
  893.  
  894. /*
  895.  * rpmv2i
  896.  *
  897.  *    relative polygon move - only (x, y). Icoord version.
  898.  */
  899. void rpmv2i(
  900.   Icoord dx,
  901.   Icoord dy)
  902. {
  903. pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  904. }
  905.  
  906. /* ------------------------------------------------------------------------ */
  907.  
  908. /*
  909.  * rpmvs
  910.  *
  911.  *    relative polygon move. Icoord version.
  912.  */
  913. void rpmvs(
  914.   Scoord dx,
  915.   Scoord dy,
  916.   Scoord dz)
  917. {
  918. pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), (vdevice.cpW[V_Z] + dz));
  919. }
  920.  
  921. /* ------------------------------------------------------------------------ */
  922.  
  923. /*
  924.  * rpmv2s
  925.  *
  926.  *    relative polygon move - only (x, y). Scoord version.
  927.  */
  928. void rpmv2s(
  929.   Scoord dx,
  930.   Scoord dy)
  931. {
  932. pmv((vdevice.cpW[V_X] + dx), (vdevice.cpW[V_Y] + dy), vdevice.cpW[V_Z]);
  933. }
  934.  
  935. /* ------------------------------------------------------------------------ */
  936.  
  937. /*
  938.  * pdri
  939.  *
  940.  *    The integer argument version of pdr.
  941.  */
  942. void pdri(
  943.   Icoord x,
  944.   Icoord y,
  945.   Icoord z)
  946. {
  947. pdr((float)x, (float)y, (float)z);
  948. }
  949.  
  950. /* ------------------------------------------------------------------------ */
  951.  
  952. /*
  953.  * pdr2i
  954.  *
  955.  *    The integer argument version of pdr2.
  956.  */
  957. void pdr2i(
  958.   Icoord x,
  959.   Icoord y)
  960. {
  961. pdr((float)x, (float)y, vdevice.cpW[V_Z]);
  962. }
  963.  
  964. /* ------------------------------------------------------------------------ */
  965.  
  966. /*
  967.  * pdrs
  968.  *
  969.  *    The short argument version of pdr.
  970.  */
  971. void pdrs(
  972.   Scoord x,
  973.   Scoord y)
  974. {
  975. pdr((float)x, (float)y, vdevice.cpW[V_Z]);
  976. }
  977.  
  978. /* ------------------------------------------------------------------------ */
  979.  
  980. /*
  981.  * pdr2s
  982.  *
  983.  *    The short argument version of pdr2.
  984.  */
  985. void pdr2s(
  986.   Scoord x,
  987.   Scoord y)
  988. {
  989. pdr((float)x, (float)y, vdevice.cpW[V_Z]);
  990. }
  991.  
  992. /* ------------------------------------------------------------------------ */
  993.  
  994. /*
  995.  * pdr2
  996.  *
  997.  *    add another vertex to the polygon array
  998.  */
  999. void pdr2(
  1000.   float x,
  1001.   float y)
  1002. {
  1003. pdr(x, y, vdevice.cpW[V_Z]);
  1004. }
  1005.  
  1006. /* ------------------------------------------------------------------------ */
  1007.  
  1008. /*
  1009.  * pclos
  1010.  *
  1011.  *    draw the polygon started by the above.
  1012.  */
  1013. void pclos(void)
  1014. {
  1015. float    lstx, lsty, lstz;
  1016. Vector    result;
  1017. int    i, j;
  1018. Token    *tok;
  1019.  
  1020. if (!vdevice.initialised)
  1021. verror("pclos: vogl not initialised");
  1022.  
  1023. vdevice.inpolygon = 0;
  1024.  
  1025. if (vdevice.inobject) {
  1026.     tok = newtokens(2 + 3 * (numv + 1));
  1027.     tok[0].i = POLYF;
  1028.     tok[1].i = numv + 1;
  1029.     for (i = 0, j = 2; i <= numv; i++, j += 3) {
  1030.         tok[j + V_X].f = p[i][V_X];
  1031.         tok[j + V_Y].f = p[i][V_Y];
  1032.         tok[j + V_Z].f = p[i][V_Z];
  1033.         }
  1034.  
  1035.     return;
  1036.     }
  1037.  
  1038. lstx = p[numv][V_X];
  1039. lsty = p[numv][V_Y];
  1040. lstz = p[numv][V_Z];
  1041.  
  1042. numv++;
  1043.  
  1044. for (i = 0; i < numv; i++) {
  1045.     multvector(result, p[i], vdevice.transmat->m);
  1046.     p[i][V_X] = result[V_X];
  1047.     p[i][V_Y] = result[V_Y];
  1048.     p[i][V_Z] = result[V_Z];
  1049.     p[i][V_W] = result[V_W];
  1050.     }
  1051.  
  1052. dopoly(numv);
  1053.  
  1054. vdevice.cpW[V_X] = lstx;
  1055. vdevice.cpW[V_Y] = lsty;
  1056. vdevice.cpW[V_Z] = lstz;
  1057. }
  1058.  
  1059. /* ------------------------------------------------------------------------ */
  1060.  
  1061. /*
  1062.  * checkbacki
  1063.  *
  1064.  *    Checks if a transformed polygon is backfacing or not.
  1065.  */
  1066. static int checkbacki(void)
  1067. {
  1068.  
  1069. #ifdef    PC    /*    Only has 16 bit ints */
  1070. #define    BACKFACE(z)    (clockwise ? ((z) <= 0L) : ((z) > 0L))
  1071. long    z;
  1072. #else
  1073. #define    BACKFACE(z)    (clockwise ? ((z) <= 0) : ((z) > 0))
  1074. int    z;
  1075. #endif
  1076.  
  1077. int    x1, x2, y1, y2;
  1078.  
  1079. x1 = ip1[1] - ip1[0];
  1080. x2 = ip1[2] - ip1[1];
  1081. y1 = ip2[1] - ip2[0];
  1082. y2 = ip2[2] - ip2[1];
  1083.  
  1084. #ifdef    PC
  1085. z = (long)x1 * (long)y2 - (long)y1 * (long)x2;
  1086. #else
  1087. z = x1 * y2 - y1 * x2;
  1088. #endif
  1089.  
  1090. return(BACKFACE(z));
  1091. }
  1092.  
  1093. /* ------------------------------------------------------------------------ */
  1094.  
  1095. /*
  1096.  * The following routines are an implementation of the Sutherland - Hodgman
  1097.  * polygon clipper, as described in "Reentrant Polygon Clipping"
  1098.  * Communications of the ACM Jan 1974, Vol 17 No. 1.
  1099.  */
  1100. static void polyclip(register int n)
  1101. {
  1102. int    i;
  1103.  
  1104. nout = 0;
  1105. for (i = 0; i < 6; i++)
  1106. first[i] = 1;
  1107.  
  1108. for (i = 0; i < n; i++) 
  1109. shclip(p[i], 0);
  1110.  
  1111. shclose(0);
  1112. }
  1113.  
  1114. /* ------------------------------------------------------------------------ */
  1115.  
  1116. static void shclip(
  1117.   float Pnt[4],
  1118.   int side)
  1119. {
  1120. float    P[4];
  1121.  
  1122. if (side == 6) {
  1123.     ip1[nout] = WtoVx(Pnt);
  1124.     ip2[nout++] = WtoVy(Pnt);
  1125.     }
  1126. else {
  1127.     copyvector(P, Pnt);
  1128.     if (first[side]) {
  1129.         first[side] = 0;
  1130.         copyvector(F[side], P);
  1131.         }
  1132.     else if (intersect(side, I, P)) {
  1133.         shclip(I, side + 1);
  1134.         }
  1135.     copyvector(S[side], P);
  1136.     if (visible(side)) 
  1137.     shclip(S[side], side + 1);
  1138.     }
  1139. }
  1140.  
  1141. /* ------------------------------------------------------------------------ */
  1142.  
  1143. static void shclose(int side)
  1144. {
  1145. if (side < 6) {
  1146.     if (intersect(side, I, F[side]))
  1147.     shclip(I, side + 1);
  1148.  
  1149.     shclose(side + 1);
  1150.  
  1151.     first[side] = 1;
  1152.     }
  1153. }
  1154.  
  1155. /* ------------------------------------------------------------------------ */
  1156.  
  1157. static intersect(
  1158.   int side,
  1159.   register Vector Ip,
  1160.   register Vector Pnt)
  1161. {
  1162. register    float    wc1, wc2, a;
  1163.  
  1164. switch (side) {
  1165. case 0:        /* x - left */
  1166.     wc1 = Pnt[3] + Pnt[0];
  1167.     wc2 = S[side][3] + S[side][0];
  1168.     break;
  1169. case 1:        /* x - right */
  1170.     wc1 = Pnt[3] - Pnt[0];
  1171.     wc2 = S[side][3] - S[side][0];
  1172.     break;
  1173. case 2:        /* y - bottom */
  1174.     wc1 = Pnt[3] + Pnt[1];
  1175.     wc2 = S[side][3] + S[side][1];
  1176.     break;
  1177. case 3:        /* y - top */
  1178.     wc1 = Pnt[3] - Pnt[1];
  1179.     wc2 = S[side][3] - S[side][1];
  1180.     break;
  1181. case 4:        /* z - near */
  1182.     wc1 = Pnt[3] + Pnt[2];
  1183.     wc2 = S[side][3] + S[side][2];
  1184.     break;
  1185. case 5:        /* z - far */
  1186.     wc1 = Pnt[3] - Pnt[2];
  1187.     wc2 = S[side][3] - S[side][2];
  1188.     break;
  1189. default:
  1190.     verror("intersect: ridiculous side value");
  1191.     }
  1192.  
  1193. if (wc1 * wc2 < 0.0) {    /* Both are opposite in sign - crosses */
  1194.     a = wc1 / (wc1 - wc2);
  1195.     if (a < 0.0 || a > 1.0) {
  1196.         return(0);
  1197.         }
  1198.     else {
  1199.         Ip[0] = Pnt[0] + a * (S[side][0] - Pnt[0]);
  1200.         Ip[1] = Pnt[1] + a * (S[side][1] - Pnt[1]);
  1201.         Ip[2] = Pnt[2] + a * (S[side][2] - Pnt[2]);
  1202.         Ip[3] = Pnt[3] + a * (S[side][3] - Pnt[3]);
  1203.         return(1);
  1204.         }
  1205.     }
  1206. return(0);
  1207. }
  1208.  
  1209. /* ------------------------------------------------------------------------ */
  1210.  
  1211. static visible(int side)
  1212. {
  1213. float    wc;
  1214.  
  1215. switch (side) {
  1216. case 0:        /* x - left */
  1217.     wc = S[side][3] + S[side][0];
  1218.     break;
  1219. case 1:        /* x - right */
  1220.     wc = S[side][3] - S[side][0];
  1221.     break;
  1222. case 2:        /* y - bottom */
  1223.     wc = S[side][3] + S[side][1];
  1224.     break;
  1225. case 3:        /* y - top */
  1226.     wc = S[side][3] - S[side][1];
  1227.     break;
  1228. case 4:        /* z - near */
  1229.     wc = S[side][3] + S[side][2];
  1230.     break;
  1231. case 5:        /* z - far */
  1232.     wc = S[side][3] - S[side][2];
  1233.     break;
  1234. default:
  1235.     verror("visible: ridiculous side value");
  1236.     }
  1237.  
  1238. return(wc >= 0.0);
  1239. }
  1240.  
  1241. /* ------------------------------------------------------------------------ */
  1242.  
  1243. /*
  1244.  * bgnpolygon
  1245.  *
  1246.  *    Set a flag so that we know what to do with v*() calls.
  1247.  */
  1248. void bgnpolygon(void)
  1249. {
  1250. if (vdevice.bgnmode != NONE)
  1251. verror("vogl: bgnpolygon mode already belongs to some other bgn routine");
  1252.  
  1253. vdevice.bgnmode = VPOLY;
  1254. vdevice.fill = polymodeflag;
  1255. vdevice.save = 1;
  1256. vdevice.inpolygon = 1;
  1257. }
  1258.  
  1259. /* ------------------------------------------------------------------------ */
  1260.  
  1261. /*
  1262.  * endpolygon
  1263.  *
  1264.  *    Set a flag so that we know what to do with v*() calls.
  1265.  */
  1266. void endpolygon(void)
  1267. {
  1268. pclos();
  1269.  
  1270. vdevice.bgnmode = NONE;
  1271. vdevice.fill = 0;
  1272. vdevice.inpolygon = 0;
  1273. vdevice.save = 0;
  1274. }
  1275.  
  1276. /* ------------------------------------------------------------------------ */
  1277.  
  1278.